Part1. 基础知识篇

Chapter1. 为什么要关心Java8

1. 代码变得更加简洁,这些代码读起来更接近问题的描述

原来:

1
2
3
4
5
Collections.sort(inventory, new Comparator<Apple>() {      
public int compare(Apple a1, Apple a2){
return a1.getWeight().compareTo(a2.getWeight());
}
});

现在:

1
inventory.sort(comparing(Apple::getWeight));

2. 对硬件也有影响

  • 在Java8以前,需要利用线程才能使用多个内核。
    • Java 1.0 中有线程和锁,甚至有一个内存模型。
    • Java 5 添加了工业级的构建模块,如线程池和并发集合
    • Java 7 添加了分支/合并(Fork/Join)框架,使得并行变得更实用,但仍然很困难
    • Java 8 对并行有了一个更简单的新思路,有更简洁的代码,且更简单地使用了多核处理器。

3. Java8 提供了一个新的API(流,Stream),支持许多处理数据的并行操作

在Java8中加入Stream可以看作另外两项扩充加入Java8中的直接原因:

  • 把代码传递给方法的简洁方式(方法引用、Lambda),这种方式简洁地表达了行为参数化,这种方式也可以让我们使用函数式编程的编程技巧。函数可以被来回传递并加以组合,以产生强大的编程语汇。
  • 接口中的默认方法

4. 几个关键概念

1) 流处理

2) 行为参数化,把代码传递给方法

3) 并行与共享的可变数据

  • 纯函数(无副作用函数、无状态函数)
  • 没有共享的可变数据,将方法和函数即代码传递给其他方法的能力,是函数式编程范式的基石

4) 方法和Lambda作为一等公民,方法引用、Lambda匿名函数(将函数作为值)

5) 外部迭代(for-each,自己去迭代集合处理元素)和内部迭代(Stream API,在库内部进行元素处理)

6) Collection API主要是为了存储和访问数据;Stream API主要用于描述对数据的计算,并且Stream提倡并行处理一个Stream中的元素,筛选一个Collection的最快方法通常是将其转换为Stream进行并行处理然后再转回为List,如

1
list.stream().filter((Apple a) -> a.getWeight() > 150).collect(Collectors.toList());

7) 默认方法,给接口设计者提供了一个扩充接口的方式,而不会破坏现有的代码。Java8在接口中使用新的default关键字来表示这一点。例如,以前需要Collection.sort(aList,aComparator),在Java8中可以直接对List调用sort方法,sort采用了默认方法,调用Collections.sort静态方法,这样List的任何实现类都不需要显式实现sort,否则会编译失败

1
2
3
default void sort(Comparator<? super E> c) {
Collections.sort(this, c);
}

8) 来自函数式编程的好思想:

  • 将方法和Lambda作为一等公民
  • 在没有可变共享状态时,函数可以有效且安全地并行执行
  • 处理null问题:Optional类,避免NPE异常
  • (结构)模式匹配,函数是分情况定义的,而不是使用if-then-else
  • 更好地利用多核处理器